package com.zq.learn.akka.typed;

import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.AbstractBehavior;
import akka.actor.typed.javadsl.ActorContext;
import akka.actor.typed.javadsl.Behaviors;
import akka.actor.typed.javadsl.Receive;

/**
 * 引导Actor
 *
 * @author ZhangQi
 * @date 2020/3/13
 */
public class GreeterMain extends AbstractBehavior<GreeterMain.SayHello> {
  //问候Actor
  private final ActorRef<Greeter.Greet> greeter;


  /**
   * 推动问候进程——Message
   */
  public static final class SayHello {
    public final String name;

    public SayHello(String name) {
      this.name = name;
    }
  }

  /**
   * 向外部提供创建方法
   *
   * @return
   */
  public static Behavior<SayHello> create() {
    return Behaviors.setup(GreeterMain::new);
  }

  /**
   * 私有构造
   *
   * @param context
   */
  private GreeterMain(ActorContext<SayHello> context) {
    super(context);
    /**
     * Actor不能使用"new"创建实例，但可用工厂的spwan()方法获取ActorRef。ActorRef指向Actor实例。
     * 此方式，因Akka为适应分布式系统。Actor位置不影响服务间调用，方便服务的容错、容灾。
     */
    // 衍生问候Actor
    this.greeter = context.spawn(Greeter.create(), "greeter");
  }

  /**
   * 接收方法（重写）
   *
   * @return
   */
  @Override public Receive<SayHello> createReceive() {
    return newReceiveBuilder().onMessage(SayHello.class, this::onSayHello).build();
  }

  /**
   * 推动问候进程
   *
   * @param command
   * @return
   */
  private Behavior<SayHello> onSayHello(SayHello command) {
    //衍生响应问候Actor
    ActorRef<Greeter.Greeted> replyTo = getContext().spawn(GreeterBot.create(3), command.name);
    greeter.tell(new Greeter.Greet(command.name, replyTo));
    return this;
  }
}
